package util;

import java.util.Random;

import org.apache.commons.math3.ode.events.EventHandler;

import model.Input;
import model.TicTacToeOligoSystemExplicitMix;

public class MyEventHandlerMultiCell extends MyEventHandler implements EventHandler {
	// from the superclass
	//public Input[] inputs; // the integer is the index in the y state array, which can take into account in which cell it was played
	
	private int dim;
	private int width;
	private int height;
	private int[][] board; //initialized with empty cells

	private static final int EMPTY_CELL = 0;
	private static final int PLAYER_A = 1;
	private static final int PLAYER_B = 2;
	
	public static final double ammount = 500;
	
	//private int whoseTurn = -1; // number of turn played by the human (PLAYER_B)
	
	public boolean correct = true;
	public boolean gameOver = false;
	
	private Random rnd = new Random();
	
	/**
	 * Handles the human player side of the game, as well as taking some metrics, such
	 * as response time
	 * @param inputs
	 * @param dim
	 * @param width
	 * @param height
	 */
	public MyEventHandlerMultiCell(int dim, int width, int height){
		super(null);
		this.whoseTurn = -1;
		this.inputs = new Input[(width*height)/2+1];
		
		for(int i=0; i< inputs.length; i++){
			inputs[i] = new Input(0,MyEventHandlerMultiCell.ammount,-1);
		}
		board = new int[width][height];
		for(int i=0;i<width;i++){
			for(int j=0;j<height;j++){
				board[i][j] = EMPTY_CELL;
			}
		}
		this.width = width;
		this.height = height;
		this.dim = dim;
	}
	
	@Override
	public Action eventOccurred(double t, double[] y, boolean increasing) {
		whoseTurn++;
		inputs[whoseTurn].timeStep = fire; // keeps track of the cells played in order
		//Detect if a new position was played by the game
		//Also, check consistency of the current state.
		int numberOfChanges = 0;
		double empty,a,b = 0;
		for(int i=0;i<width;i++){
			for(int j=0;j<height;j++){
				empty = y[dim*(i*height+j)+TicTacToeOligoSystemExplicitMix.offsetEmpty];
				a = y[dim*(i*height+j)+TicTacToeOligoSystemExplicitMix.offsetA];
				b = y[dim*(i*height+j)+TicTacToeOligoSystemExplicitMix.offsetB];
				if(board[i][j]==MyEventHandlerMultiCell.EMPTY_CELL){
					if(empty < a || empty < b){ //something was played
						numberOfChanges++;
						board[i][j] = a < b ? MyEventHandlerMultiCell.PLAYER_B : MyEventHandlerMultiCell.PLAYER_A;
						correct = correct && a > b; // player A was supposed to play
					}
				} else if ( board[i][j]==MyEventHandlerMultiCell.PLAYER_A){
					if(a < empty || a < b){
						System.out.println("Kochi?");
						correct = false;
						return EventHandler.Action.STOP; //incorrect behavior
					}
				} else if ( board[i][j]==MyEventHandlerMultiCell.PLAYER_B){
					if(b < empty || b < a){
						System.out.println("Yappari kochi");
						correct = false;
						return EventHandler.Action.STOP; //incorrect behavior
					}
				} else {
					System.err.println("Incorrect board state");
					correct = false;
					return EventHandler.Action.STOP; //incorrect behavior
				}
			}
		}
		if((numberOfChanges != 1 && whoseTurn > 0 ) || (numberOfChanges !=0 && whoseTurn == 0) || !correct){
			//Has to generate something about it?
			return EventHandler.Action.STOP;
		}
		
		return EventHandler.Action.RESET_STATE;
	}

	@Override
	public double g(double t, double[] y) {
		// stays at the same value until a stable state is detected. Then fire within 1 time unit (minutes in real life)
		return (this.fire == -1 || gameOver?this.value :value*(fire-t+1)); 
	}

	@Override
	public void resetState(double t, double[] y) {
		// The "human" player plays randomly.
		if (whoseTurn == width*height/2 -1){
			gameOver = true;
		}
		int cell = 3;//rnd.nextInt(width*height- 2*whoseTurn - 1); // number of remaining free cells
		// find the corresponding empty cell
		int i = 0,j = -1;
		while(cell >= 0){
			if(j<height-1){
				j++;
			} else {
				i++;
				j=0;
			}
			if(board[i][j]==MyEventHandlerMultiCell.EMPTY_CELL){
				cell--;
			}
		}
		// now, I have the coordinates;
		inputs[whoseTurn].receivingSeq = dim*(i*height+j)+TicTacToeOligoSystemExplicitMix.offsetB;
			if (t == fire){
				y[inputs[whoseTurn].receivingSeq] = y[inputs[whoseTurn].receivingSeq] + inputs[whoseTurn].ammount;
				board[i][j] = PLAYER_B; // the human player played there
			}
		
		value = - value;
		fire = -1;
	}

}
